如前面所介紹的,在Xcode 12 創建新的 SwiftUI 專案視窗,在初始配置有一個改變,就是多了 Life Cycle 選單,前面我們新增過 UIKit App Delegate 的專案了,這邊我們就來新增看看 SwiftUI App 的專案
新建完成後,我們來看一下它自動產生的檔案,來跟前面的 Life Cycle - UIKit App Delegate 專案比較,發現專案沒有 AppDelegate
或 SceneDelegate
來處理 App 的生命週期及其各種狀態了,代替的是一個與專案名字相同的檔案,加上 "App" 後綴,例如HelloWorldApp.swift
檔案:
我們來看看這些修改做了些什麼
HelloWorldApp.swift
中 HelloWorldApp struct 被加了 @main
屬性標記,以表示這是 App 的 entry point,而且不可能會有多於一個結構被這樣標記,它將在調用時初始化應用程序Scene
,這是另一個協定,根據官方文件,它是一個要顯示給使用者的視圖層次結構 (view hierarchy) 的容器。每個場景都包含視圖層次結構的根視圖,並具有由系統管理的生命週期SwiftUI 將整個原有的平台差異部分抽象為 App 和Scene,對於一個mac/iOS/iPad/watch/tv/..應用程序來說,App 代表了整個應用,Scene 代表了與Window 相關的多窗口,有些設備只有一個Scene 有些則有多個,雖然不同的OS 確實存在差異,但是在語義層面達到了一致
以下我們再對 SwiftUI App 或 SwiftUI App Lifecycle 做進一步的介紹
App States Callbacks
在 iOS 14 中,Apple 提供了 ScenePhase 來追蹤應用程序的狀態。 場景的狀態在環境中被追蹤,因此我們創建了 @Environment 屬性來訪問當前值,然後使用 onChange(of:)
修飾符來監聽狀態的任何變化。
@main
struct HelloWorldApp: App {
@Environment(\.scenePhase) var scenePhase
var body: some Scene {
WindowGroup {
ContentView()
}.onChange(of: scenePhase) { (newScenePhase) in
switch newScenePhase {
case .background:
print("App State : Background")
case .inactive:
print("App State : Inactive")
case .active:
print("App State : Active")
@unknown default:
print("App State : Unknown")
}
}
}
}
有關更多詳細信息,請參考官方文件
Deeplink URLs
在 UIKit 方法中,我們通過在AppDelegate 中 回調application(_:open:options:)
方法處理所有深層鏈接 url,但是在 SwiftUI 中,我們可以通過將 onOpenURL
修飾符附加到應用程序的最頂層場景來處理傳入的 url。 它在閉包中返回傳入的 url
ContentView()
.onOpenURL(perform: { url in
print("Incoming url: \(url)")
})
App Init
對於基本初始化,可以像在 AppDelegate 的 didFinishLaunchWithOptions
方法中一樣執行初始化,或者如果您正在使用某些第三方並且需要在應用程序啟動時進行設置, SwiftUI App 換在 struct HelloWorldApp
的 init
方法中進行初始化操作
範例:
@main
struct HelloWorldApp: App {
@Environment(\.scenePhase) var scenePhase
init() {
// perform any task on app launch
}
var body: some Scene {
WindowGroup {
ContentView()
.onOpenURL(perform: { url in
print("Incoming url: \(url)")
})
}.onChange(of: scenePhase) { (newScenePhase) in
switch newScenePhase {
case .background:
print("App State : Background")
case .inactive:
print("App State : Inactive")
case .active:
print("App State : Active")
@unknown default:
print("App State : Unknown")
}
}
}
}
AppDelegate in SwiftUI
如果您有一些需求一定要用到 AppDelegate 的話,那麼 SwiftUI 提供了一種通過使用 @UIApplicationDelegateAdaptor
在 SwiftUI 生命週期內使用 AppDelegate 的方法
@UIApplicationDelegateAdaptor
提供了使用 UIApplicationDelegate
方法的選項,這些方法通常在 UIKit 應用程序中使用
首先添加一個文件來創建 AppDelegate 類別,例如創建一個"MyAppDelegate.swift"後,裡面內容為 "MyAppDelegate" 類別,它繼承自 "UIResponder" 並有實作 "UIApplicationDelegate" 協定,然後添加didFinishLaunchWithOptions
方法
創建 AppDelegate 後,現在通過 @UIApplicationDelegateAdaptor
屬性包裝器將其附加到結構 "HelloWorldApp" 的入口點
在調用場景 init 方法後,即會調用 AppDelegate 的 didFinishLaunchWithOptions
方法。
以上就簡單介紹了關於新的 SwiftUI 生命週期更新的基礎
參考文件:Bye Bye AppDelegate! SwiftUI App Life Cycle